package messages;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import security.Hash;
import security.crypto.AssimEncryption;
import utils.Base64Processing;
import utils.XmlSerializationUtils;

public class CcSKExchangeMessage implements Convertible {

	private static final long serialVersionUID = 1L;
	
	private String _cipheredSessionKey;
	private String _sessionKeyAuth;

	public CcSKExchangeMessage() {
	}
	
	public CcSKExchangeMessage(SecretKey sessionKey, PublicKey clientPublicKey, PrivateKey serverPrivateKey){
		String keysHash = Hash.getKeysHash(sessionKey, clientPublicKey);
		_sessionKeyAuth = AssimEncryption.signHash(keysHash, serverPrivateKey);
		
		String sessionKeyString = Base64Processing.encodeData(sessionKey.getEncoded());
		_cipheredSessionKey = AssimEncryption.cipher(sessionKeyString, clientPublicKey);
	}
	
	public SecretKey getSessionKey(KeyPair clientKeyPair, PublicKey serverPublicKey) {
		
		String sessionKeyString = AssimEncryption.decipher(_cipheredSessionKey, clientKeyPair.getPrivate());
		byte[] sessionKeyBytes = Base64Processing.decodeData(sessionKeyString);
		SecretKey sessionKey = new SecretKeySpec(sessionKeyBytes, "AES");
		
		String originalMessage = Hash.getKeysHash(sessionKey, clientKeyPair.getPublic());
		boolean validKey = AssimEncryption.validateSignature(originalMessage, _sessionKeyAuth, serverPublicKey);
		
		if(validKey)
			return sessionKey;
		else
			return null;
	}

	@Override
	public Element convertToCanonic(Document doc) {
		Element el = doc.createElement("CcSKExchangeMessage");

		if (_cipheredSessionKey != null) {
			Element childEl = doc.createElement("CipheredSessionKey");
			childEl.setTextContent(_cipheredSessionKey);
			el.appendChild(childEl);
		} 
		
		if (_sessionKeyAuth != null) {
			Element childEl = doc.createElement("SessionKeyAuthenticator");
			childEl.setTextContent(_sessionKeyAuth);
			el.appendChild(childEl);
		} 
		
		return el;
	}

	@Override
	public Object convertFromCanonic(Element el) {
		this._cipheredSessionKey = XmlSerializationUtils.getTextValue(el, "CipheredSessionKey");
		this._sessionKeyAuth = XmlSerializationUtils.getTextValue(el, "SessionKeyAuthenticator");
		return this;
	}
}
